// --------------------------------------------------------------------------------------------------------------------
// <copyright file="URDataPackagesTest.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Test.Robotics.Hardware.UniversalRobots
{
    using System;
    using Microsoft.Robotics.Hardware.UniversalRobots;
    using Microsoft.Robotics.Numerics;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Tests for the classes contained in URDataPackages.
    /// </summary>
    [TestClass]
    public class URDataPackagesTests
    {
        /// <summary>
        /// Number of joints
        /// </summary>
        private const int NumJoints = 6;

        /// <summary>
        /// Robot mode package packet fragment
        /// </summary>
        private byte[] robotModeTestPackageBytes = 
        {
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x14,
            0x8a,
            0xea,
            0x01,
            0x01,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x07,
            0x3f,
            0xf0,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00
       };

        /// <summary>
        /// Joint data package packet fragment
        /// </summary>
        private byte[] jointDataTestPacket = 
        {
            62,
            241,
            83,
            40,
            120,
            141,
            46,
            253,
            188,
            141,
            44,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            190,
            177,
            232,
            252,
            66,
            64,
            0,
            0,
            65,
            199,
            51,
            51,
            66,
            12,
            0,
            0,
            239,
            191,
            249,
            33,
            244,
            28,
            123,
            87,
            234,
            191,
            249,
            33,
            251,
            84,
            68,
            45,
            24,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            189,
            92,
            97,
            3,
            66,
            63,
            153,
            154,
            65,
            199,
            51,
            51,
            66,
            18,
            204,
            205,
            239,
            62,
            244,
            51,
            52,
            192,
            220,
            0,
            0,
            60,
            119,
            124,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            189,
            37,
            72,
            194,
            66,
            63,
            153,
            154,
            65,
            200,
            0,
            0,
            66,
            18,
            0,
            0,
            239,
            191,
            249,
            33,
            241,
            228,
            92,
            120,
            254,
            191,
            249,
            33,
            251,
            84,
            68,
            45,
            25,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            188,
            96,
            224,
            96,
            66,
            63,
            153,
            154,
            65,
            215,
            51,
            51,
            66,
            28,
            0,
            0,
            239,
            62,
            230,
            177,
            226,
            177,
            189,
            221,
            16,
            188,
            86,
            8,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            190,
            101,
            143,
            184,
            66,
            63,
            153,
            154,
            65,
            199,
            51,
            51,
            66,
            20,
            0,
            0,
            239,
            62,
            247,
            53,
            200,
            59,
            5,
            129,
            68,
            188,
            131,
            52,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            189,
            181,
            38,
            135,
            66,
            62,
            102,
            103,
            65,
            202,
            102,
            103,
            66,
            23,
            51,
            51,
            239
        };

        /// <summary>
        /// Additional info packet
        /// </summary>
        private byte[] additionalInfoPacket =
        {
            0,
            1
        };

        /// <summary>
        /// Force mode packet
        /// </summary>
        private byte[] forceModePacket = 
        {
            63,
            217,
            71,
            108,
            128,
            85,
            50,
            154,
            191,
            218,
            98,
            23,
            207,
            38,
            168,
            44,
            63,
            218,
            104,
            89,
            146,
            110,
            25,
            57,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            191,
            227,
            193,
            68,
            180,
            68,
            244,
            246,
            63,
            121,
            69,
            245,
            227,
            234,
            65,
            10
        };

        /// <summary>
        /// Packet fragment containing configuration data
        /// </summary>
        private byte[] configurationDataPackage = new byte[]
        {
            192,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            192,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            192,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            192,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            192,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            192,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            25,
            33,
            251,
            84,
            68,
            45,
            24,
            64,
            9,
            51,
            51,
            51,
            51,
            51,
            51,
            64,
            46,
            0,
            0,
            0,
            0,
            0,
            0,
            64,
            9,
            51,
            51,
            51,
            51,
            51,
            51,
            64,
            46,
            0,
            0,
            0,
            0,
            0,
            0,
            64,
            9,
            51,
            51,
            51,
            51,
            51,
            51,
            64,
            46,
            0,
            0,
            0,
            0,
            0,
            0,
            64,
            9,
            153,
            153,
            153,
            153,
            153,
            154,
            64,
            57,
            0,
            0,
            0,
            0,
            0,
            0,
            64,
            9,
            153,
            153,
            153,
            153,
            153,
            154,
            64,
            57,
            0,
            0,
            0,
            0,
            0,
            0,
            64,
            9,
            153,
            153,
            153,
            153,
            153,
            154,
            64,
            57,
            0,
            0,
            0,
            0,
            0,
            0,
            63,
            240,
            193,
            82,
            56,
            45,
            115,
            101,
            63,
            246,
            87,
            24,
            74,
            231,
            68,
            135,
            63,
            208,
            0,
            0,
            0,
            0,
            0,
            0,
            63,
            243,
            51,
            51,
            51,
            51,
            51,
            51,
            63,
            208,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            191,
            219,
            51,
            51,
            51,
            51,
            51,
            51,
            191,
            217,
            26,
            159,
            190,
            118,
            200,
            180,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            63,
            182,
            211,
            31,
            205,
            36,
            225,
            97,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            63,
            187,
            241,
            65,
            32,
            91,
            192,
            26,
            63,
            184,
            58,
            251,
            126,
            144,
            255,
            151,
            63,
            181,
            17,
            156,
            224,
            117,
            246,
            253,
            63,
            249,
            33,
            251,
            84,
            82,
            69,
            80,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            63,
            249,
            33,
            251,
            84,
            82,
            69,
            80,
            191,
            249,
            33,
            251,
            84,
            82,
            69,
            80,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            5,
            0,
            0,
            0,
            2,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            1,
            0,
            0,
            0,
            2,
            0,
            0,
            0,
            2,
            0,
            0,
            0,
            2,
            0,
            0,
            0,
            2,
            0,
            0,
            0,
            2,
            0,
            0,
            0,
            2,
        };

        /// <summary>
        /// Cartesian info package packet fragment
        /// </summary>
        private byte[] cartesianInfoPackage = 
        {
            190,
            240,
            215,
            115,
            134,
            192,
            58,
            211,
            191,
            200,
            129,
            111,
            1,
            90,
            185,
            130,
            63,
            240,
            4,
            86,
            113,
            21,
            180,
            181,
            62,
            239,
            254,
            235,
            232,
            49,
            29,
            141,
            64,
            1,
            197,
            130,
            40,
            97,
            164,
            255,
            192,
            1,
            197,
            130,
            40,
            79,
            37,
            144
        };

        /// <summary>
        /// Packet fragment for master board data package.
        /// </summary>
        private byte[] masterboardDataPackage = 
        {
            0,
            0,
            0,
            0,
            0,
            0,
            63,
            78,
            1,
            224,
            30,
            1,
            224,
            30,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            66,
            37,
            153,
            154,
            66,
            65,
            153,
            154,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            5,
            0,
            0
        };

        /// <summary>
        /// Packet fragment for tool data package
        /// </summary>
        private byte[] toolDataPackage =
        {
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            24,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            239
        };

        /// <summary>
        /// Expected joint positions for the Joint Data packet fragment.
        /// </summary>
        private double[] expectedJointPositions = 
        {
            0.0,
            -MathConstants.PIOverTwo,
            0.0,
            -MathConstants.PIOverTwo,
            0.0,
            0.0
        };

        /// <summary>
        /// Expected joint positions for the Joint Data packet fragment.
        /// </summary>
        private double[] expectedJointVoltages = 
        {
            48.0,
            47.9,
            47.9,
            47.9,
            47.9,
            47.6
        };

        /// <summary>
        /// Expected joint temperatures for the Joint Data packet fragment.
        /// </summary>
        private double[] expectedJointTemps = 
        {
            24.9,
            24.9,
            25.0,
            26.9,
            24.9,
            25.300001144
        };

        /// <summary>
        /// Expected DH a parameters
        /// </summary>
        private double[] expectedDHa =
        {
            0.0,
            -0.425,
            -0.39225,
            0.0,
            0.0,
            0.0
        };

        /// <summary>
        /// Expected DH d parameters
        /// </summary>
        private double[] expectedDHd =
        {
            0.089159,
            0.0,
            0.0,
            0.10915,
            0.09465,
            0.0823
        };

        /// <summary>
        /// Expected DH theta parameters
        /// </summary>
        private double[] expectedDHTheta =
        {
            0,
            0,
            0,
            0,
            0,
            0
        };

        /// <summary>
        /// Expected DH alpha parameters
        /// </summary>
        private double[] expectedDHAlpha =
        {
            1.570796327,
            0.0,
            0.0,
            1.570796327,
            -1.570796327,
            0.0
        };

        /// <summary>
        /// Expected joint acceleration
        /// </summary>
        private double[] expectedJointAcceleration =
        {
            15.0,
            15.0,
            15.0,
            25.0,
            25.0,
            25.0
        };

        /// <summary>
        /// Expected joint position max limit
        /// </summary>
        private double[] expectedJointMaxLimit =
        {
            6.2831853071795862,
            6.2831853071795862,
            6.2831853071795862,
            6.2831853071795862,
            6.2831853071795862,
            6.2831853071795862
        };

        /// <summary>
        /// Expected joint position max speed
        /// </summary>
        private double[] expectedJointMaxSpeed = 
        {
            3.15,
            3.15,
            3.15,
            3.2,
            3.2,
            3.2
        };

        /// <summary>
        /// Expected joint position min limit
        /// </summary>
        private double[] expectedJointMinLimit =
        {
            -6.2831853071795862,
            -6.2831853071795862,
            -6.2831853071795862,
            -6.2831853071795862,
            -6.2831853071795862,
            -6.2831853071795862
        };

        /// <summary>
        /// Expected motor type
        /// </summary>
        private int[] expectedMotorType =
        {
            2,
            2,
            2,
            2,
            2,
            2
        };

        /// <summary>
        /// Expected Cartesian pose of the TCP
        /// </summary>
        private Pose expectedTcpCartesianPose = new Pose(
            new Vector3(
                    -0.0000160614076066223,
                    -0.191450000539954,
                    1.00105899976488),
                new Quaternion(
                    0.00000485638792595049,
                    0.707106781263314,
                    -0.70710678109195,
                    0.00000127766052788174));

        /// <summary>
        /// Test building Robot Mode Package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingRobotModePackage()
        {
            ControllerData robotModePackageContainer = new ControllerData(this.robotModeTestPackageBytes);

            Assert.AreEqual(true, robotModePackageContainer.IsPhysicalRobotConnected);
            Assert.AreEqual(true, robotModePackageContainer.IsRealRobotEnabled);
            Assert.AreEqual(false, robotModePackageContainer.IsRobotPowerOn);
            Assert.AreEqual(false, robotModePackageContainer.IsEmergencyStopped);
            Assert.AreEqual(false, robotModePackageContainer.IsSecurityStopped);
            Assert.AreEqual(false, robotModePackageContainer.IsProgramRunning);
            Assert.AreEqual(false, robotModePackageContainer.IsProgramPaused);
            Assert.AreEqual(URDataPackages.RobotModes.NoPower, robotModePackageContainer.RobotMode);
            Assert.AreEqual(1, robotModePackageContainer.SpeedFraction);
        }

        /// <summary>
        /// Test building Joint Data Package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingJointDataPackage()
        {
            JointChainData jointDataPackageContainer = new JointChainData(this.jointDataTestPacket);
            for (int i = 0; i < NumJoints; ++i)
            {
                Assert.AreEqual(this.expectedJointPositions[i], jointDataPackageContainer.JointData[i].ActualPositionInRadians, 0.01);
                Assert.AreEqual(this.expectedJointPositions[i], jointDataPackageContainer.JointData[i].TargetPositionInRadians, 0.01);
                Assert.AreEqual(0.0, jointDataPackageContainer.JointData[i].SpeedInRadPerSec, 0.01);
                Assert.AreEqual(this.expectedJointVoltages[i], jointDataPackageContainer.JointData[i].Voltage, 1);
                Assert.AreEqual(URDataPackages.JointModes.PowerOff, jointDataPackageContainer.JointData[i].Mode);
                Assert.AreEqual(this.expectedJointTemps[i], jointDataPackageContainer.JointData[i].MotorTempInDegC, MathConstants.ErrorEpsilon);
            }
        }

        /// <summary>
        /// Test building additional info package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingAdditionalInfoPackage()
        {
            AdditionalInfo additionalInfo = new AdditionalInfo(this.additionalInfoPacket);

            Assert.AreEqual(false, additionalInfo.IsTeachButtonPressed);
            Assert.AreEqual(true, additionalInfo.IsTeachButtonEnabled);
        }

        /// <summary>
        /// Test building additional info package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingForceModePackage()
        {
            TcpForceData tcpForceData = new TcpForceData(this.forceModePacket);
            Assert.AreEqual(0.0061702351655557128, tcpForceData.RobotDexterity, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, tcpForceData.Rx, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, tcpForceData.Ry, MathConstants.ErrorEpsilon);
            Assert.AreEqual(-0.617342331017112, tcpForceData.Rz, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.39498436481952981, tcpForceData.X, MathConstants.ErrorEpsilon);
            Assert.AreEqual(-0.41223712186422534, tcpForceData.Y, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.41261901187717204, tcpForceData.Z, MathConstants.ErrorEpsilon);
        }

        /// <summary>
        /// Test building configuration package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingConfigurationPackage()
        {
            ConfigurationData configurationData = new ConfigurationData(this.configurationDataPackage);

            for (int i = 0; i < NumJoints; ++i)
            {
                Assert.AreEqual(this.expectedDHa[i], configurationData.A[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedDHd[i], configurationData.D[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedDHAlpha[i], configurationData.Alpha[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedDHTheta[i], configurationData.Theta[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedJointAcceleration[i], configurationData.JointMaxAcceleration[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedJointMaxSpeed[i], configurationData.JointMaxSpeed[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedJointMinLimit[i], configurationData.JointMinLimit[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(this.expectedJointMaxLimit[i], configurationData.JointMaxLimit[i], MathConstants.ErrorEpsilon);
                Assert.AreEqual(2, configurationData.MotorType[i]);
            }

            Assert.AreEqual(1.3962634015954636, configurationData.AJointDefault, MathConstants.ErrorEpsilon);
            Assert.AreEqual(1.2, configurationData.AToolDefault, MathConstants.ErrorEpsilon);
            Assert.AreEqual(2, configurationData.ControllerBoxType);
            Assert.AreEqual(0.25, configurationData.EqRadius, MathConstants.ErrorEpsilon);
            Assert.AreEqual(5, configurationData.MasterboardVersion);
            Assert.AreEqual(1, configurationData.RobotType);
            Assert.AreEqual(1, configurationData.RobotSubType);
            Assert.AreEqual(1.0471975511965976, configurationData.VJointDefault, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.25, configurationData.VToolDefault, MathConstants.ErrorEpsilon);
        }

        /// <summary>
        /// Test building Cartesian info package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingCartesianInfoPackage()
        {
            CartesianData cartesianData = new CartesianData(this.cartesianInfoPackage);

            Assert.AreEqual(cartesianData.CartesianPose, this.expectedTcpCartesianPose);
        }

        /// <summary>
        /// Test building master board data package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingMasterboardInfoPackage()
        {
            MasterboardData masterboardData = new MasterboardData(this.masterboardDataPackage);

            Assert.AreEqual(0.0009157091575091575, masterboardData.AnalogInput0, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, masterboardData.AnalogInput1, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0, masterboardData.AnalogInputRange0);
            Assert.AreEqual(0, masterboardData.AnalogInputRange1);
            Assert.AreEqual(0.0, masterboardData.AnalogOutput0, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, masterboardData.AnalogOutput1, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0, masterboardData.AnalogOutputDomain0);
            Assert.AreEqual(0, masterboardData.AnalogOutputDomain1);
            Assert.AreEqual(0, masterboardData.DigitalInputBits);
            Assert.AreEqual(0, masterboardData.DigitalOutputBits);
            Assert.AreEqual(false, masterboardData.IsEuromap67Installed);
            Assert.AreEqual(41.4f, masterboardData.MasterboardTemperature, (float)MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, masterboardData.MasterIOCurrent, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0, masterboardData.MasterOnOffState);
            Assert.AreEqual(5, masterboardData.MasterSafetyState);
            Assert.AreEqual(0.0, masterboardData.RobotCurrent, MathConstants.ErrorEpsilon);
            Assert.AreEqual(48.4f, masterboardData.RobotVoltage48V, (float)MathConstants.ErrorEpsilon);
        }
 
        /// <summary>
        /// Test building tool data package
        /// </summary>
        [TestMethod]
        [TestCategory("Unit")]
        [Priority(0)]
        public void TestBlittingToolDataPackage()
        {
            ToolData toolData = new ToolData(this.toolDataPackage);
            Assert.AreEqual(0.0, toolData.AnalogInput2, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, toolData.AnalogInput3, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0, toolData.AnalogInputRange2);
            Assert.AreEqual(0, toolData.AnalogInputRange3);
            Assert.AreEqual(0.0, toolData.ToolCurrent, MathConstants.ErrorEpsilon);
            Assert.AreEqual(239, toolData.ToolMode);
            Assert.AreEqual(24, toolData.ToolOutputVoltage);
            Assert.AreEqual(0.0, toolData.ToolTemperature, MathConstants.ErrorEpsilon);
            Assert.AreEqual(0.0, toolData.ToolVoltage48V, MathConstants.ErrorEpsilon);
        }
    }
}
